package middlewares

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/zeromicro/go-zero/core/logx"
)

// GlobalJsonMiddleware 全局 JSON 中间件
func GlobalJsonMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 设置 JSON 响应头
		w.Header().Set("Content-Type", "application/json; charset=utf-8")

		// 创建包装的 ResponseWriter
		rw := &responseWrapper{
			ResponseWriter: w,
			statusCode:     http.StatusOK,
		}

		defer func() {
			if recovered := recover(); recovered != nil {
				handlePanic(rw, recovered)
			}

			// 如果是错误响应，确保是 JSON 格式
			if rw.statusCode >= 400 && !rw.bodyWritten {
				handleErrorJson(rw, rw.statusCode, rw.errorMessage)
			}
		}()

		// 执行完上述异常或者错误之后前端响应状态则为大于400
		// 强制性设置将响应状态设置为200
		rw.WriteHeader(200)
		next(rw, r)

	}
}

type responseWrapper struct {
	http.ResponseWriter
	statusCode   int
	bodyWritten  bool
	errorMessage string
}

func (rw *responseWrapper) WriteHeader(code int) {
	rw.statusCode = code
	rw.ResponseWriter.WriteHeader(code)
}

func (rw *responseWrapper) Write(data []byte) (int, error) {
	if rw.statusCode >= 400 {
		rw.errorMessage = string(data)
		// 暂不写入，在 defer 中统一处理为 JSON
		return len(data), nil
	}
	rw.bodyWritten = true
	return rw.ResponseWriter.Write(data)
}

func handlePanic(w http.ResponseWriter, r interface{}) {
	logx.Errorf("Panic recovered: %v", r)

	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.WriteHeader(http.StatusInternalServerError)

	json.NewEncoder(w).Encode(map[string]interface{}{
		"code":        http.StatusInternalServerError,
		"data":        nil,
		"message":     fmt.Sprintf("%v", r),
		"status_code": http.StatusInternalServerError,
	})
}

func handleErrorJson(w http.ResponseWriter, statusCode int, message string) {
	jsonData, _ := json.Marshal(map[string]interface{}{
		"code":        statusCode,
		"data":        nil,
		"message":     message,
		"status_code": statusCode,
	})
	w.WriteHeader(200)
	w.Write(jsonData)
}
